package gptma.fo.utils;

import javax.el.ELContext;
import javax.faces.FactoryFinder;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public final class JSFUtils {

	private JSFUtils() {
		// utility class, do not instanciate
	}

	/**
	 * Retourne le bean correspondant, null si pas de correspondance ou si l'on
	 * ne se trouve pas dans un contexte JSF
	 * 
	 * @param beanName
	 * @return le bean correspondant à l'expression
	 */
	public static Object getJsfBean(String beanName) {
		return getJsfBean(beanName, FacesContext.getCurrentInstance());
	}

	/**
	 * Retourne le bean correspondant, null si pas de correspondance ou si l'on
	 * ne se trouve pas dans un contexte JSF
	 * 
	 * @param beanName
	 * @param context
	 * @param req
	 * @param res
	 * @return le bean correspondant à l'expression
	 */
	public static Object getJsfBean(String beanName, ServletContext context,
			HttpServletRequest req, HttpServletResponse res) {
		FacesContext ctx = getFacesContext(context, req, res);
		Object ret = getJsfBean(beanName, ctx);
		ctx.release();

		return ret;
	}

	/**
	 * Retourne le bean correspondant à partir du contexte (peut être créé
	 * manuellement), null si pas de correspondance ou si l'on ne se trouve pas
	 * dans un contexte JSF
	 * 
	 * @param beanName
	 * @param context
	 * @return
	 */
	private static Object getJsfBean(String beanName, FacesContext context) {
		Object ret = null;
		if (context != null) {
			ELContext ectx = context.getELContext();
			ret = ectx.getELResolver().getValue(ectx, null, beanName);
		}

		return ret;
	}

	/**
	 * Retourne le FacesContext courant. S'il n'est pas atteignable (ds un
	 * filtre en amont par exemple), on le créé. Req: ne pas oublier
	 * d'appeller release() dessus une fois utilisé
	 * 
	 * @see http://wiki.apache.org/myfaces/InvokingJsfPagesWithStandardUrls
	 */
	private static FacesContext getFacesContext(ServletContext context,
			HttpServletRequest req, HttpServletResponse res) {
		FacesContext ret = null;

		ret = FacesContext.getCurrentInstance();
		if (ret == null) {

			FacesContextFactory fcFactory = (FacesContextFactory) FactoryFinder
					.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
			ret = fcFactory.getFacesContext(context, req, res, getLifeCycle());
		}

		return ret;
	}

	/**
	 * Retourne l'instance du LifeCycle
	 * 
	 * @return
	 */
	private static Lifecycle getLifeCycle() {
		LifecycleFactory lFactory = (LifecycleFactory) FactoryFinder
				.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
		return lFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
	}
}
